1use crate::intrinsics;
2use crate::iter::{TrustedLen, TrustedRandomAccess, from_fn};
3use crate::num::NonZero;
4use crate::ops::{Range, Try};
5use crate::range::RangeIter;
6
7#[must_use = "iterators are lazy and do nothing unless consumed"]
15#[stable(feature = "iterator_step_by", since = "1.28.0")]
16#[derive(Clone, Debug)]
17pub struct StepBy<I> {
18 iter: I,
25 step_minus_one: usize,
30 first_take: bool,
31}
32
33impl<I> StepBy<I> {
34 #[inline]
35 pub(in crate::iter) fn new(iter: I, step: usize) -> StepBy<I> {
36 assert!(step != 0);
37 let iter = <I as SpecRangeSetup<I>>::setup(iter, step);
38 StepBy { iter, step_minus_one: step - 1, first_take: true }
39 }
40
41 #[inline]
44 fn original_step(&self) -> NonZero<usize> {
45 unsafe { NonZero::new_unchecked(intrinsics::unchecked_add(self.step_minus_one, 1)) }
48 }
49}
50
51#[stable(feature = "iterator_step_by", since = "1.28.0")]
52impl<I> Iterator for StepBy<I>
53where
54 I: Iterator,
55{
56 type Item = I::Item;
57
58 #[inline]
59 fn next(&mut self) -> Option<Self::Item> {
60 self.spec_next()
61 }
62
63 #[inline]
64 fn size_hint(&self) -> (usize, Option<usize>) {
65 self.spec_size_hint()
66 }
67
68 #[inline]
69 fn nth(&mut self, n: usize) -> Option<Self::Item> {
70 self.spec_nth(n)
71 }
72
73 fn try_fold<Acc, F, R>(&mut self, acc: Acc, f: F) -> R
74 where
75 F: FnMut(Acc, Self::Item) -> R,
76 R: Try<Output = Acc>,
77 {
78 self.spec_try_fold(acc, f)
79 }
80
81 #[inline]
82 fn fold<Acc, F>(self, acc: Acc, f: F) -> Acc
83 where
84 F: FnMut(Acc, Self::Item) -> Acc,
85 {
86 self.spec_fold(acc, f)
87 }
88}
89
90impl<I> StepBy<I>
91where
92 I: ExactSizeIterator,
93{
94 fn next_back_index(&self) -> usize {
97 let rem = self.iter.len() % self.original_step();
98 if self.first_take { if rem == 0 { self.step_minus_one } else { rem - 1 } } else { rem }
99 }
100}
101
102#[stable(feature = "double_ended_step_by_iterator", since = "1.38.0")]
103impl<I> DoubleEndedIterator for StepBy<I>
104where
105 I: DoubleEndedIterator + ExactSizeIterator,
106{
107 #[inline]
108 fn next_back(&mut self) -> Option<Self::Item> {
109 self.spec_next_back()
110 }
111
112 #[inline]
113 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
114 self.spec_nth_back(n)
115 }
116
117 fn try_rfold<Acc, F, R>(&mut self, init: Acc, f: F) -> R
118 where
119 F: FnMut(Acc, Self::Item) -> R,
120 R: Try<Output = Acc>,
121 {
122 self.spec_try_rfold(init, f)
123 }
124
125 #[inline]
126 fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
127 where
128 Self: Sized,
129 F: FnMut(Acc, Self::Item) -> Acc,
130 {
131 self.spec_rfold(init, f)
132 }
133}
134
135#[stable(feature = "iterator_step_by", since = "1.28.0")]
137impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {}
138
139#[unstable(feature = "trusted_len", issue = "37572")]
145unsafe impl<I> TrustedLen for StepBy<I> where I: Iterator + TrustedRandomAccess {}
146
147trait SpecRangeSetup<T> {
148 fn setup(inner: T, step: usize) -> T;
149}
150
151impl<T> SpecRangeSetup<T> for T {
152 #[inline]
153 default fn setup(inner: T, _step: usize) -> T {
154 inner
155 }
156}
157
158unsafe trait StepByImpl<I> {
169 type Item;
170
171 fn spec_next(&mut self) -> Option<Self::Item>;
172
173 fn spec_size_hint(&self) -> (usize, Option<usize>);
174
175 fn spec_nth(&mut self, n: usize) -> Option<Self::Item>;
176
177 fn spec_try_fold<Acc, F, R>(&mut self, acc: Acc, f: F) -> R
178 where
179 F: FnMut(Acc, Self::Item) -> R,
180 R: Try<Output = Acc>;
181
182 fn spec_fold<Acc, F>(self, acc: Acc, f: F) -> Acc
183 where
184 F: FnMut(Acc, Self::Item) -> Acc;
185}
186
187unsafe trait StepByBackImpl<I> {
198 type Item;
199
200 fn spec_next_back(&mut self) -> Option<Self::Item>
201 where
202 I: DoubleEndedIterator + ExactSizeIterator;
203
204 fn spec_nth_back(&mut self, n: usize) -> Option<Self::Item>
205 where
206 I: DoubleEndedIterator + ExactSizeIterator;
207
208 fn spec_try_rfold<Acc, F, R>(&mut self, init: Acc, f: F) -> R
209 where
210 I: DoubleEndedIterator + ExactSizeIterator,
211 F: FnMut(Acc, Self::Item) -> R,
212 R: Try<Output = Acc>;
213
214 fn spec_rfold<Acc, F>(self, init: Acc, f: F) -> Acc
215 where
216 I: DoubleEndedIterator + ExactSizeIterator,
217 F: FnMut(Acc, Self::Item) -> Acc;
218}
219
220unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
221 type Item = I::Item;
222
223 #[inline]
224 default fn spec_next(&mut self) -> Option<I::Item> {
225 let step_size = if self.first_take { 0 } else { self.step_minus_one };
226 self.first_take = false;
227 self.iter.nth(step_size)
228 }
229
230 #[inline]
231 default fn spec_size_hint(&self) -> (usize, Option<usize>) {
232 #[inline]
233 fn first_size(step: NonZero<usize>) -> impl Fn(usize) -> usize {
234 move |n| if n == 0 { 0 } else { 1 + (n - 1) / step }
235 }
236
237 #[inline]
238 fn other_size(step: NonZero<usize>) -> impl Fn(usize) -> usize {
239 move |n| n / step
240 }
241
242 let (low, high) = self.iter.size_hint();
243
244 if self.first_take {
245 let f = first_size(self.original_step());
246 (f(low), high.map(f))
247 } else {
248 let f = other_size(self.original_step());
249 (f(low), high.map(f))
250 }
251 }
252
253 #[inline]
254 default fn spec_nth(&mut self, mut n: usize) -> Option<I::Item> {
255 if self.first_take {
256 self.first_take = false;
257 let first = self.iter.next();
258 if n == 0 {
259 return first;
260 }
261 n -= 1;
262 }
263 let mut step = self.original_step().get();
266 if n == usize::MAX {
269 self.iter.nth(step - 1);
270 } else {
271 n += 1;
272 }
273
274 loop {
276 let mul = n.checked_mul(step);
277 {
278 if intrinsics::likely(mul.is_some()) {
279 return self.iter.nth(mul.unwrap() - 1);
280 }
281 }
282 let div_n = usize::MAX / n;
283 let div_step = usize::MAX / step;
284 let nth_n = div_n * n;
285 let nth_step = div_step * step;
286 let nth = if nth_n > nth_step {
287 step -= div_n;
288 nth_n
289 } else {
290 n -= div_step;
291 nth_step
292 };
293 self.iter.nth(nth - 1);
294 }
295 }
296
297 default fn spec_try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
298 where
299 F: FnMut(Acc, Self::Item) -> R,
300 R: Try<Output = Acc>,
301 {
302 #[inline]
303 fn nth<I: Iterator>(
304 iter: &mut I,
305 step_minus_one: usize,
306 ) -> impl FnMut() -> Option<I::Item> + '_ {
307 move || iter.nth(step_minus_one)
308 }
309
310 if self.first_take {
311 self.first_take = false;
312 match self.iter.next() {
313 None => return try { acc },
314 Some(x) => acc = f(acc, x)?,
315 }
316 }
317 from_fn(nth(&mut self.iter, self.step_minus_one)).try_fold(acc, f)
318 }
319
320 default fn spec_fold<Acc, F>(mut self, mut acc: Acc, mut f: F) -> Acc
321 where
322 F: FnMut(Acc, Self::Item) -> Acc,
323 {
324 #[inline]
325 fn nth<I: Iterator>(
326 iter: &mut I,
327 step_minus_one: usize,
328 ) -> impl FnMut() -> Option<I::Item> + '_ {
329 move || iter.nth(step_minus_one)
330 }
331
332 if self.first_take {
333 self.first_take = false;
334 match self.iter.next() {
335 None => return acc,
336 Some(x) => acc = f(acc, x),
337 }
338 }
339 from_fn(nth(&mut self.iter, self.step_minus_one)).fold(acc, f)
340 }
341}
342
343unsafe impl<I: DoubleEndedIterator + ExactSizeIterator> StepByBackImpl<I> for StepBy<I> {
344 type Item = I::Item;
345
346 #[inline]
347 default fn spec_next_back(&mut self) -> Option<Self::Item> {
348 self.iter.nth_back(self.next_back_index())
349 }
350
351 #[inline]
352 default fn spec_nth_back(&mut self, n: usize) -> Option<I::Item> {
353 let n = n.saturating_mul(self.original_step().get()).saturating_add(self.next_back_index());
358 self.iter.nth_back(n)
359 }
360
361 default fn spec_try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
362 where
363 F: FnMut(Acc, Self::Item) -> R,
364 R: Try<Output = Acc>,
365 {
366 #[inline]
367 fn nth_back<I: DoubleEndedIterator>(
368 iter: &mut I,
369 step_minus_one: usize,
370 ) -> impl FnMut() -> Option<I::Item> + '_ {
371 move || iter.nth_back(step_minus_one)
372 }
373
374 match self.next_back() {
375 None => try { init },
376 Some(x) => {
377 let acc = f(init, x)?;
378 from_fn(nth_back(&mut self.iter, self.step_minus_one)).try_fold(acc, f)
379 }
380 }
381 }
382
383 #[inline]
384 default fn spec_rfold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
385 where
386 Self: Sized,
387 F: FnMut(Acc, I::Item) -> Acc,
388 {
389 #[inline]
390 fn nth_back<I: DoubleEndedIterator>(
391 iter: &mut I,
392 step_minus_one: usize,
393 ) -> impl FnMut() -> Option<I::Item> + '_ {
394 move || iter.nth_back(step_minus_one)
395 }
396
397 match self.next_back() {
398 None => init,
399 Some(x) => {
400 let acc = f(init, x);
401 from_fn(nth_back(&mut self.iter, self.step_minus_one)).fold(acc, f)
402 }
403 }
404 }
405}
406
407trait AsLegacyRange<T> {
429 fn as_legacy_range(&self) -> &Range<T>;
430 fn as_legacy_range_mut(&mut self) -> &mut Range<T>;
431}
432
433impl<T> AsLegacyRange<T> for Range<T> {
434 #[inline]
435 fn as_legacy_range(&self) -> &Range<T> {
436 self
437 }
438 #[inline]
439 fn as_legacy_range_mut(&mut self) -> &mut Range<T> {
440 self
441 }
442}
443
444impl<T> AsLegacyRange<T> for RangeIter<T> {
445 #[inline]
446 fn as_legacy_range(&self) -> &Range<T> {
447 &self.0
448 }
449 #[inline]
450 fn as_legacy_range_mut(&mut self) -> &mut Range<T> {
451 &mut self.0
452 }
453}
454
455macro_rules! spec_int_ranges {
456 ($ctor:ident; $($t:ty)*) => ($(
457
458 const _: () = assert!(usize::BITS >= <$t>::BITS);
459
460 impl SpecRangeSetup<$ctor<$t>> for $ctor<$t> {
461 #[inline]
462 fn setup(mut r: $ctor<$t>, step: usize) -> $ctor<$t> {
463 let inner_len = r.size_hint().0;
464 let yield_count = inner_len.div_ceil(step);
467 r.as_legacy_range_mut().end = yield_count as $t;
469 r
470 }
471 }
472
473 unsafe impl StepByImpl<$ctor<$t>> for StepBy<$ctor<$t>> {
474 #[inline]
475 fn spec_next(&mut self) -> Option<$t> {
476 let step = <$t>::try_from(self.original_step().get()).unwrap_or(<$t>::MAX);
479 let r = self.iter.as_legacy_range_mut();
480 let remaining = r.end;
481 if remaining > 0 {
482 let val = r.start;
483 r.start = val.wrapping_add(step);
486 r.end = remaining - 1;
487 Some(val)
488 } else {
489 None
490 }
491 }
492
493 #[inline]
494 fn spec_size_hint(&self) -> (usize, Option<usize>) {
495 let remaining = self.iter.as_legacy_range().end as usize;
496 (remaining, Some(remaining))
497 }
498
499 #[inline]
503 fn spec_nth(&mut self, n: usize) -> Option<Self::Item> {
504 self.advance_by(n).ok()?;
505 self.next()
506 }
507
508 #[inline]
509 fn spec_try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
510 where
511 F: FnMut(Acc, Self::Item) -> R,
512 R: Try<Output = Acc>
513 {
514 let mut accum = init;
515 while let Some(x) = self.next() {
516 accum = f(accum, x)?;
517 }
518 try { accum }
519 }
520
521 #[inline]
522 fn spec_fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
523 where
524 F: FnMut(Acc, Self::Item) -> Acc
525 {
526 let step = <$t>::try_from(self.original_step().get()).unwrap_or(<$t>::MAX);
529 let r = self.iter.as_legacy_range();
530 let remaining = r.end;
531 let mut acc = init;
532 let mut val = r.start;
533 for _ in 0..remaining {
534 acc = f(acc, val);
535 val = val.wrapping_add(step);
538 }
539 acc
540 }
541 }
542 )*)
543}
544
545macro_rules! spec_int_ranges_r {
546 ($ctor:ident; $($t:ty)*) => ($(
547 const _: () = assert!(usize::BITS >= <$t>::BITS);
548
549 unsafe impl StepByBackImpl<$ctor<$t>> for StepBy<$ctor<$t>> {
550
551 #[inline]
552 fn spec_next_back(&mut self) -> Option<Self::Item> {
553 let step = self.original_step().get() as $t;
554 let r = self.iter.as_legacy_range_mut();
555 let remaining = r.end;
556 if remaining > 0 {
557 let start = r.start;
558 r.end = remaining - 1;
559 Some(start + step * (remaining - 1))
560 } else {
561 None
562 }
563 }
564
565 #[inline]
569 fn spec_nth_back(&mut self, n: usize) -> Option<Self::Item> {
570 if self.advance_back_by(n).is_err() {
571 return None;
572 }
573 self.next_back()
574 }
575
576 #[inline]
577 fn spec_try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
578 where
579 F: FnMut(Acc, Self::Item) -> R,
580 R: Try<Output = Acc>
581 {
582 let mut accum = init;
583 while let Some(x) = self.next_back() {
584 accum = f(accum, x)?;
585 }
586 try { accum }
587 }
588
589 #[inline]
590 fn spec_rfold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
591 where
592 F: FnMut(Acc, Self::Item) -> Acc
593 {
594 let mut accum = init;
595 while let Some(x) = self.next_back() {
596 accum = f(accum, x);
597 }
598 accum
599 }
600 }
601 )*)
602}
603
604#[cfg(target_pointer_width = "64")]
613mod step_by_spec {
614 use super::*;
615 spec_int_ranges!(Range; u8 u16 u32 u64 usize);
616 spec_int_ranges!(RangeIter; u8 u16 u32 u64 usize);
617 spec_int_ranges_r!(Range; u8 u16 u32 usize);
618 spec_int_ranges_r!(RangeIter; u8 u16 usize);
619}
620
621#[cfg(target_pointer_width = "32")]
622mod step_by_spec {
623 use super::*;
624 spec_int_ranges!(Range; u8 u16 u32 usize);
625 spec_int_ranges!(RangeIter; u8 u16 u32 usize);
626 spec_int_ranges_r!(Range; u8 u16 u32 usize);
627 spec_int_ranges_r!(RangeIter; u8 u16 usize);
628}
629
630#[cfg(target_pointer_width = "16")]
631mod step_by_spec {
632 use super::*;
633 spec_int_ranges!(Range; u8 u16 usize);
634 spec_int_ranges!(RangeIter; u8 u16 usize);
635 spec_int_ranges_r!(Range; u8 u16 usize);
636 spec_int_ranges_r!(RangeIter; u8 u16 usize);
637}